package com.cg.springSecurity.config;


import com.cg.springSecurity.security.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.UrlAuthorizationConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.csrf.CsrfFilter;
import org.springframework.web.filter.CharacterEncodingFilter;

import javax.annotation.Resource;

@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    //登录成功处理器
    @Resource
    private CustomizeAuthenticationSuccessHandler authenticationSuccessHandler;
    //登录失败处理器
    @Autowired
    private CustomizeAuthenticationFailureHandler authenticationFailureHandler;

    //注销处理器
    @Autowired
    private CustomizeLogoutSuccessHandler logoutSuccessHandler;

    //异常处理器
    @Autowired
    private CustomizeAuthenticationEntryPoint authenticationEntryPoint;

//    jwt验证
    @Autowired
    private JwtLoginFilter jwtLoginFilter;
    //注销处理器
    @Autowired
    private JwtLogoutHandler logoutHandler;
    //用户权限映射
    @Autowired
    CustomSecurityMetadataSource customSecurityMetadataSource;
    //访问权限不足处理器
    @Autowired
    MyAccessDeniedHandler accessDeniedHandler;
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //添加转码,防止中文乱码
        CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
        encodingFilter.setEncoding("UTF-8");
        encodingFilter.setForceEncoding(true);
        http.addFilterBefore(encodingFilter, CsrfFilter.class);
        http.addFilterBefore(jwtLoginFilter, UsernamePasswordAuthenticationFilter.class);
        //配置没有权限访问跳转自定义页面
//        http.exceptionHandling().accessDeniedPage("/403.html");
        http.logout()
                .logoutUrl("/user/logout")
                .addLogoutHandler(logoutHandler)
////                .logoutSuccessUrl("/user/logout")
                .logoutSuccessHandler(logoutSuccessHandler)
//                .deleteCookies("JSESSIONID")//删除cookie
                .permitAll();
        //关闭默认登陆页面
//        http.removeConfigurer(DefaultLoginPageConfigurer.class);

        //添加自定义权限管理器
        ApplicationContext applicationContext = http.getSharedObject(ApplicationContext.class);
        http.apply(new UrlAuthorizationConfigurer<>(applicationContext))
                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
                    @Override
                    public <O extends FilterSecurityInterceptor> O postProcess(O object) {
                        // 使用配置好的CustomSecurityMetadataSource来代替默认的SecurityMetadataSource对象
                        object.setSecurityMetadataSource(customSecurityMetadataSource);
                        // 将rejectPublicInvocations设置为true，表示当getAttributes返回null时，不允许访问受保护对象
                        object.setRejectPublicInvocations(false);
                        return object;
                    }
                });
        //禁止session验证
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        http.formLogin()   //自定义自己编写的登陆页面
//                .loginPage("/login.html")  //登陆页面设置
                .loginProcessingUrl("/user/login")  //登陆访问路径
                .successHandler(authenticationSuccessHandler)
//                .defaultSuccessUrl("/success" , true) //登陆成功后跳转路径
//                .successForwardUrl("/")
//                .failureUrl("/user/fail")//登录失败跳转的路径
                .failureHandler(authenticationFailureHandler)
                .permitAll()
                .and().exceptionHandling()
                .accessDeniedHandler(accessDeniedHandler)
                .authenticationEntryPoint(authenticationEntryPoint)//登陆异常处理
                .and().authorizeRequests()
                .antMatchers("/user/**","/**/info","/img/**",
                        "/swagger-ui.html", "/v2/**", "/swagger-resources/**", "/webjars/springfox-swagger-ui/**")
                .permitAll()//不拦截的路径
                .anyRequest().authenticated()
                .and()
                .rememberMe().rememberMeParameter("remember_me")
                .userDetailsService(userDetailsService)
                .and()
                .csrf()
                .disable();  //关闭csrf的保护
        http.cors();//开启跨域
    }
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(password());

    }

    @Bean
    PasswordEncoder password(){
        return new BCryptPasswordEncoder();
    }

}
